package org.formatter.common;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import com.sun.org.apache.xerces.internal.util.DOMUtil;

public class DomUtil {

	/** Finds and returns the first child node with the given name. */
	public static Element getFirstChildElement(Node parent, String elemName) {

		// search for node
		Node child = parent.getFirstChild();
		while (child != null) {
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				if (child.getNodeName().equals(elemName)) {
					return (Element) child;
				}
			}
			child = child.getNextSibling();
		}

		// not found
		return null;

	}

	/**
	 * Returns the concatenated child text of the specified node. This method
	 * only looks at the immediate children of type <code>Node.TEXT_NODE</code>
	 * or the children of any child node that is of type
	 * <code>Node.CDATA_SECTION_NODE</code> for the concatenation.
	 * 
	 * @param node
	 *            The node to look at.
	 */
	public static String getChildText(Node node) {

		// is there anything to do?
		if (node == null) {
			return null;
		}

		// concatenate children text
		StringBuffer str = new StringBuffer();
		Node child = node.getFirstChild();
		while (child != null) {
			short type = child.getNodeType();
			if (type == Node.TEXT_NODE) {
				str.append(child.getNodeValue());
			} else if (type == Node.CDATA_SECTION_NODE) {
				str.append(getChildText(child));
			}
			child = child.getNextSibling();
		}

		// return text value
		return str.toString();

	}
	public static void writeToOutputStream(Document doc, OutputStream out)
			throws TransformerException {
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		DOMSource source = new DOMSource(doc);
		StreamResult result = new StreamResult(out);
		transformer.transform(source, result);
	}

	public static void writeToOutputStream(Node node, OutputStream out)
			throws TransformerException {
		Document doc = DOMUtil.getDocument(node);
		if (DOMUtil.getRoot(doc) == null) {
			doc.appendChild(node);
		}
		writeToOutputStream(doc, out);
	}

	public static Document read2Doc(InputStream in) throws ParserConfigurationException, SAXException, IOException  {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document doc = null;
		DocumentBuilder builder = factory.newDocumentBuilder();
		doc = builder.parse(in);
		doc.normalize();
		return doc;
	}
}
